package core

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

type ErrorResponser interface {
	setMessage(message string)
	getMessage() string

	addError(code int, messge string)
	getErrors() []map[int]string

	setCode(code int)
	getCode() int
}

type ErrorResponse struct {
	ErrorMessage string
	ErrorCode    int
	ErrorList    []map[int]string
}

func (e *ErrorResponse) setCode(code int) {
	e.ErrorCode = code
}

func (e *ErrorResponse) getCode() int {
	return e.ErrorCode
}

func (e *ErrorResponse) setMessage(message string) {
	e.ErrorMessage = message
}

func (e *ErrorResponse) getMessage() string {
	return e.ErrorMessage
}

func (e *ErrorResponse) addError(code int, message string) {
	e.ErrorList = append(e.ErrorList, map[int]string{code: message})
}

func (e *ErrorResponse) getErrors() []map[int]string {
	return e.ErrorList
}

// 定义错误码
const (

	// 客户端错误
	ErrorBadRequrest      = 401000
	ErrorMethodNotAllowed = 405000

	// 服务端错误
	ErrorInternalServerError = 500000
	ErrorDecodeJson          = 550001
	ErrorDeployError         = 550002
)

var errorCodeList = map[int]string{
	// 客户端错误
	ErrorBadRequrest:      "客户端错误",
	ErrorMethodNotAllowed: "请求方法错误",

	// 服务端错误
	ErrorInternalServerError: "服务端错误",
	ErrorDecodeJson:          "JSON解码失败",
	ErrorDeployError:         "部署失败",
}

type Responser interface {
	Success(data interface{})
	InternalServerError(errorCode int)
	BadRequest(errorCode int)
	Unauthorized(errorCode int)
	NotFound(errorCode int)
	Forbidden(errorCode int)
	MethodNotAllowed(errorCode int)
	AddErrorList(errorCode int)
	AddError(cusErrorCode int, cusErrorMessage string)

	SetResponseWriter(w http.ResponseWriter)
	GetResponseWriter() http.ResponseWriter
	Response()

	setErrorResponse(errorResponse ErrorResponser)
	getErrorResponse() ErrorResponser
	setStatus(status int)
	getStatus() int
	setData(data interface{})
	getData() interface{}
	getResponseJson(data interface{}) string
}

type Response struct {
	responseWriter http.ResponseWriter
	status         int
	data           interface{}
	errorResponse  ErrorResponser
}

func (r *Response) setData(data interface{}) {
	r.data = data
}

func (r *Response) getData() interface{} {
	return r.data
}

func (r *Response) setStatus(status int) {
	r.status = status
}

func (r *Response) getStatus() int {
	return r.status
}

func (r *Response) getResponseJson(data interface{}) string {
	if data == nil {
		return "{}"
	}

	ret, err := json.Marshal(data)
	if err != nil {
		var errorResponse ErrorResponser = new(ErrorResponse)
		errorResponse.setCode(ErrorDecodeJson)
		errorResponse.setMessage(fmt.Sprintf("JSON encode Fail (%s)", err))
		return r.getResponseJson(errorResponse)
	}
	return string(ret)
}

func (r *Response) getInitErrorResponse() ErrorResponser {
	var errorResponse ErrorResponser = r.getErrorResponse()
	if errorResponse == nil {
		errorResponse = new(ErrorResponse)
	}
	return errorResponse
}

func (r *Response) assemblyErrorMessage(errorCode int) {
	errorResponse := r.getInitErrorResponse()
	errorMessage := errorCodeList[errorCode]
	errorResponse.setCode(errorCode)
	errorResponse.setMessage(errorMessage)
	r.setErrorResponse(errorResponse)
}

func (r *Response) assemblyErrorList(errorCode int) {
	errorResponse := r.getInitErrorResponse()
	errorMessage := errorCodeList[errorCode]
	errorResponse.addError(errorCode, errorMessage)
	r.setErrorResponse(errorResponse)
}

func (r *Response) setErrorResponse(errorResponse ErrorResponser) {
	r.errorResponse = errorResponse
}

func (r *Response) getErrorResponse() ErrorResponser {
	return r.errorResponse
}

func (r *Response) SetResponseWriter(w http.ResponseWriter) {
	r.responseWriter = w
}

func (r *Response) GetResponseWriter() http.ResponseWriter {
	return r.responseWriter
}

func (r *Response) Response() {
	if r.getStatus() == 0 {
		r.setStatus(http.StatusOK)
	}

	r.GetResponseWriter().WriteHeader(r.getStatus())
	if r.getStatus() == http.StatusOK {
		io.WriteString(r.GetResponseWriter(), r.getResponseJson(r.getData()))
	} else {
		io.WriteString(r.GetResponseWriter(), r.getResponseJson(r.getErrorResponse()))
	}
}

func (r *Response) InternalServerError(errorCode int) {
	r.setStatus(http.StatusInternalServerError)
	r.assemblyErrorMessage(errorCode)
	r.Response()
}

func (r *Response) BadRequest(errorCode int) {
	r.setStatus(http.StatusBadRequest)
	r.assemblyErrorMessage(errorCode)
	r.Response()
}

func (r *Response) Unauthorized(errorCode int) {
	r.setStatus(http.StatusUnauthorized)
	r.assemblyErrorMessage(errorCode)
	r.Response()
}

func (r *Response) Forbidden(errorCode int) {
	r.setStatus(http.StatusForbidden)
	r.assemblyErrorMessage(errorCode)
	r.Response()
}

func (r *Response) NotFound(errorCode int) {
	r.setStatus(http.StatusNotFound)
	r.assemblyErrorMessage(errorCode)
	r.Response()
}

func (r *Response) MethodNotAllowed(errorCode int) {
	r.setStatus(http.StatusMethodNotAllowed)
	r.assemblyErrorMessage(errorCode)
	r.Response()
}

func (r *Response) Success(data interface{}) {
	r.setStatus(http.StatusOK)
	r.setData(data)
	r.Response()
}

func (r *Response) AddErrorList(errorCode int) {
	r.assemblyErrorList(errorCode)
}

func (r *Response) AddError(cusErrorCode int, cusErrorMessage string) {
	errorResponse := r.getInitErrorResponse()
	errorResponse.addError(cusErrorCode, cusErrorMessage)
	r.setErrorResponse(errorResponse)
}
